package com.weido.nettyServer.nettyMvc;

import com.weido.nettyServer.annotation.Path;
import com.weido.nettyServer.annotation.RespJson;
import com.weido.nettyServer.utils.ScanClassUtil;
import io.netty.util.internal.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 处理路由映射
 */
@Component
public class MappingHandler {
    @Autowired
    private ApplicationContext context;

    protected static ConcurrentHashMap<String, Class<?>> classMap = new ConcurrentHashMap<>();
    protected static ConcurrentHashMap<String, Method> methodMap = new ConcurrentHashMap<>();
    //存放被@RespJson修饰的类
    protected final static Set<Class<?>> classRespJsons = Collections.synchronizedSet(new HashSet<Class<?>>());
    //存放被@RespJson修饰的方法
    protected final static Set<Method> methodRespJsons = Collections.synchronizedSet(new HashSet<Method>());


    public void init(String basePackage) {

        System.out.println("---MethodHandler 初始化开始---");
        //获取web.xml中配置的要扫描的包
        if (StringUtil.isNullOrEmpty(basePackage)) {
            throw new RuntimeException("无效的包名！");
        }
        //配置了多个包
        if (basePackage.indexOf(",") > 0) {
            //按逗号进行分隔
            String[] packageNameArr = basePackage.split(",");
            for (String packageName : packageNameArr) {
                add2ClassMap(packageName);
            }
        } else {
            add2ClassMap(basePackage);
        }
        System.out.println("----MethodHandler初始化结束---");
    }

    /**
     * 将被注解修饰的类
     *
     * @param packageName
     */
    private void add2ClassMap(String packageName) {
        Set<Class<?>> setClasses = ScanClassUtil.getClasses(packageName);
        for (Class<?> clazz : setClasses) {
            String pathAttrValue = null;
            //判断类被注解修饰
            if (clazz.isAnnotationPresent(Path.class)) {
                //获取path的Annotation的实例
                Path pathInstance = clazz.getAnnotation(Path.class);
                //获取Annotation的实例的value属性的值
                pathAttrValue = pathInstance.value();
                if (StringUtils.isNotEmpty(pathAttrValue)) {
                    pathAttrValue = handPathStr(pathAttrValue);
                    classMap.put(pathAttrValue, clazz);
                }
            }
            if (clazz.isAnnotationPresent(RespJson.class)) {
                classRespJsons.add(clazz);
            }
            //判断方法被注解修饰
            Method[] methods = clazz.getMethods();
            for (Method m : methods) {
                //判断方法被注解修饰
                if (m.isAnnotationPresent(Path.class)) {
                    //获取path的Annotation的实例
                    Path pathInstance = m.getAnnotation(Path.class);
                    //获取Annotation的实例的value属性的值
                    String methodPathValue = pathInstance.value();
                    if (StringUtils.isNotEmpty(methodPathValue)) {
                        methodPathValue = handPathStr(methodPathValue);
                        pathAttrValue = handPathStr(pathAttrValue);
                        methodMap.put(pathAttrValue + methodPathValue, m);
                    }
                }
                if (m.isAnnotationPresent(RespJson.class)) {
                    methodRespJsons.add(m);
                }
            }
        }
    }

    /**
     * 判断是否可以获得方法
     *
     * @param url
     * @return
     */
    public boolean hasMethod(String url) {
        if (StringUtil.isNullOrEmpty(url)) {
            return false;
        }
        return methodMap.containsKey(url);
    }

    /**
     * 获取方法
     *
     * @param url
     * @return
     */
    public Method getMethod(String url) {
        if (hasMethod(url)) {
            return methodMap.get(url);
        }
        return null;
    }


    /**
     * 处理一下路径，前面后面的斜杠
     *
     * @param pathStr
     * @return
     */
    private String handPathStr(String pathStr) {
        if (pathStr.endsWith("/")) {
            pathStr = pathStr.substring(0, pathStr.length() - 1);
        }
        if (!pathStr.startsWith("/")) {
            pathStr = "/" + pathStr;
        }
        return pathStr;
    }

    public MappingHandler(String packagename) {
        init(packagename);
    }
    public MappingHandler() {
    }


    public ConcurrentHashMap<String, Class<?>> getClassMap() {
        return classMap;
    }


    public ConcurrentHashMap<String, Method> getMethodMap() {
        return methodMap;
    }


    public static Set<Class<?>> getClassRespJsons() {
        return classRespJsons;
    }

    public static Set<Method> getMethodRespJsons() {
        return methodRespJsons;
    }

    public void setClassMap(ConcurrentHashMap<String, Class<?>> classMap) {
        this.classMap = classMap;
    }

    public void setMethodMap(ConcurrentHashMap<String, Method> methodMap) {
        this.methodMap = methodMap;
    }
}
